home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / orca / mouse_review.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  11.2 KB  |  330 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Mouse review mode.'''
  5. __id__ = '$Id: mouse_review.py 4221 2008-09-15 08:11:23Z wwalker $'
  6. __version__ = '$Revision: 4221 $'
  7. __date__ = '$Date: 2008-09-15 04:11:23 -0400 (Mon, 15 Sep 2008) $'
  8. __copyright__ = 'Copyright (c) 2008 Eitan Isaacson'
  9. __license__ = 'LGPL'
  10. import debug
  11.  
  12. try:
  13.     import wnck
  14.     _mouseReviewCapable = True
  15. except:
  16.     debug.println(debug.LEVEL_WARNING, 'Python module wnck not found, mouse review not available.')
  17.     _mouseReviewCapable = False
  18.  
  19. import gtk
  20. import gobject
  21. import orca
  22. import pyatspi
  23. import speech
  24. import braille
  25. import settings
  26.  
  27. class BoundingBox:
  28.     '''A bounding box, currently it is used to test if a given point is
  29.     inside the bounds of the box.
  30.     '''
  31.     
  32.     def __init__(self, x, y, width, height):
  33.         '''Initialize a bounding box.
  34.  
  35.         Arguments:
  36.         - x: Left border of box.
  37.         - y: Top border of box.
  38.         - width: Width of box.
  39.         - height: Height of box.
  40.         '''
  41.         (self.x, self.y, self.width, self.height) = (x, y, width, height)
  42.  
  43.     
  44.     def isInBox(self, x, y):
  45.         '''Test if a given point is inside a box.
  46.  
  47.         Arguments:
  48.         - x: X coordinate.
  49.         - y: Y coordinate.
  50.  
  51.         Returns True if point is inside box.
  52.         '''
  53.         if x <= x:
  54.             pass
  55.         elif x <= self.x + self.width:
  56.             if y <= y:
  57.                 return y <= self.y + self.height
  58.             y <= y
  59.         return y
  60.  
  61.  
  62.  
  63. class _WordContext:
  64.     '''A word on which the mouse id hovering above. This class should have
  65.     enough info to make it unique, so we know when we have left the word.
  66.     '''
  67.     
  68.     def __init__(self, word, acc, start, end):
  69.         '''Initialize a word context.
  70.  
  71.         Arguments:
  72.         - word: The string of the word we are on.
  73.         - acc: The accessible object that contains the word.
  74.         - start: The start offset of the word in the text.
  75.         - end: The end offset of the word in the text.
  76.         '''
  77.         self.word = word
  78.         self.acc = acc
  79.         self.start = start
  80.         self.end = end
  81.  
  82.     
  83.     def __cmp__(self, other):
  84.         '''Compare two word contexts, if they refer to the same word, return 0.
  85.         Otherwise return 1
  86.         '''
  87.         if other is None:
  88.             return 1
  89.         if self.word == other.word and self.acc == other.acc and self.start == other.start:
  90.             pass
  91.         return int(not (self.end == other.end))
  92.  
  93.  
  94.  
  95. class _ItemContext:
  96.     '''An _ItemContext holds all the information of the item we are currently
  97.     hovering above. If the accessible supports word speaking, we also store
  98.     a word context here.
  99.     '''
  100.     
  101.     def __init__(self, x = 0, y = 0, acc = None, frame = None, app = None, script = None):
  102.         """Initialize an _ItemContext with all the information we have.
  103.  
  104.         Arguments:
  105.         - x: The X coordinate of the pointer.
  106.         - y: The Y coordinate of the pointer.
  107.         - acc: The end-node accessible at that coordinate.
  108.         - frame: The top-level frame below the pointer.
  109.         - app: The application the pointer is hovering above.
  110.         - script: The script for the context's application.
  111.         """
  112.         self.acc = acc
  113.         self.frame = frame
  114.         self.app = app
  115.         self.script = script
  116.         self.word_ctx = self._getWordContext(x, y)
  117.  
  118.     
  119.     def _getWordContext(self, x, y):
  120.         """If the context's accessible supports it, retrieve the word we are
  121.         currently hovering above.
  122.  
  123.         Arguments:
  124.         - x: The X coordinate of the pointer.
  125.         - y: The Y coordinate of the pointer.
  126.  
  127.         Returns a _WordContext of the current word, or None.
  128.         """
  129.         if not (self.script) or not self.script.speakWordUnderMouse(self.acc):
  130.             return None
  131.         (word, start, end) = self.script.getWordAtCoords(self.acc, x, y)
  132.         return _WordContext(word, self.acc, start, end)
  133.  
  134.  
  135.  
  136. class MouseReviewer:
  137.     '''Main class for the mouse-review feature.
  138.     '''
  139.     
  140.     def __init__(self):
  141.         '''Initalize a mouse reviewer class.
  142.         '''
  143.         if not _mouseReviewCapable:
  144.             return None
  145.         wnck_screen = wnck.screen_get_default()
  146.         self.active = False
  147.         self._currentMouseOver = _ItemContext()
  148.         self._oldMouseOver = _ItemContext()
  149.         self._lastReportedCoord = None
  150.  
  151.     
  152.     def toggle(self, on = None):
  153.         '''Toggle mouse reviewing on or off.
  154.  
  155.         Arguments:
  156.         - on: If set to True or False, explicitly toggles reviewing on or off.
  157.         '''
  158.         if not _mouseReviewCapable:
  159.             return None
  160.         if on is None:
  161.             on = not (self.active)
  162.         
  163.         if on and not (self.active):
  164.             pyatspi.Registry.registerEventListener(self._onMouseMoved, 'mouse:abs')
  165.         elif not on and self.active:
  166.             pyatspi.Registry.deregisterEventListener(self._onMouseMoved, 'mouse:abs')
  167.         
  168.         self.active = on
  169.  
  170.     
  171.     def _onMouseMoved(self, event):
  172.         '''Callback for "mouse:abs" AT-SPI event. We will check after the dwell
  173.         delay if the mouse moved away, if it didn\'t we will review the
  174.         component under it.
  175.  
  176.         Arguments:
  177.         - event: The event we recieved.
  178.         '''
  179.         if settings.mouseDwellDelay:
  180.             gobject.timeout_add(settings.mouseDwellDelay, self._mouseDwellTimeout, event.detail1, event.detail2)
  181.         else:
  182.             self._mouseDwellTimeout(event.detail1, event.detail2)
  183.  
  184.     
  185.     def _mouseDwellTimeout(self, prev_x, prev_y):
  186.         '''Dwell timout callback. If we are still dwelling, review the
  187.         component.
  188.  
  189.         Arguments:
  190.         - prev_x: Previuos X coordinate of mouse pointer.
  191.         - prev_y: Previuos Y coordinate of mouse pointer.
  192.         '''
  193.         display = gtk.gdk.Display(gtk.gdk.get_display())
  194.         (screen, x, y, flags) = display.get_pointer()
  195.         if abs(prev_x - x) <= settings.mouseDwellMaxDrift and abs(prev_y - y) <= settings.mouseDwellMaxDrift and not ((x, y) == self._lastReportedCoord):
  196.             self._lastReportedCoord = (x, y)
  197.             self._reportUnderMouse(x, y)
  198.         
  199.         return False
  200.  
  201.     
  202.     def _reportUnderMouse(self, x, y):
  203.         '''Report the element under the given coordinates:
  204.  
  205.         Arguments:
  206.         - x: X coordinate.
  207.         - y: Y coordinate.
  208.         '''
  209.         current_element = self._getContextUnderMouse(x, y)
  210.         if not current_element:
  211.             return None
  212.         self._currentMouseOver = current_element
  213.         self._oldMouseOver = self._currentMouseOver
  214.         output_obj = []
  215.         if current_element.acc.getRole() in (pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_COMBO_BOX) and current_element.acc.getState().contains(pyatspi.STATE_SELECTED):
  216.             return None
  217.         if (self._currentMouseOver.acc != self._oldMouseOver.acc or settings.mouseDwellDelay > 0) and not (self._currentMouseOver.word_ctx):
  218.             output_obj.append(self._currentMouseOver.acc)
  219.         
  220.         if self._currentMouseOver.word_ctx:
  221.             if self._currentMouseOver.word_ctx != self._oldMouseOver.word_ctx:
  222.                 output_obj.append(self._currentMouseOver.word_ctx.word)
  223.             
  224.         
  225.         self._outputElements(output_obj)
  226.         return False
  227.  
  228.     
  229.     def _outputElements(self, output_obj):
  230.         '''Output the given elements.
  231.         TODO: Now we are mainly using WhereAmI, we might need to find out a
  232.         better, less verbose output method.
  233.  
  234.         Arguments:
  235.         - output_obj: A list of objects to output, could be accessibles and
  236.         text.
  237.         '''
  238.         if output_obj:
  239.             speech.stop()
  240.         
  241.         for obj in output_obj:
  242.             if obj is None:
  243.                 continue
  244.             
  245.             if isinstance(obj, str):
  246.                 speech.speak(obj)
  247.                 braille.displayMessage(obj)
  248.                 continue
  249.             speech.speakUtterances(self._currentMouseOver.script.speechGenerator.getSpeech(obj, False))
  250.             self._currentMouseOver.script.updateBraille(obj)
  251.         
  252.  
  253.     
  254.     def _getZOrder(self, frame_name):
  255.         '''Determine the stack position of a given window.
  256.  
  257.         Arguments:
  258.         - frame_name: The name of the window.
  259.  
  260.         Returns position of given window in window-managers stack.
  261.         '''
  262.         wnck_screen = wnck.screen_get_default()
  263.         window_order = [ w.get_name() for w in wnck_screen.get_windows_stacked() ]
  264.         return window_order.index(frame_name)
  265.  
  266.     
  267.     def _getContextUnderMouse(self, x, y):
  268.         '''Get the context under the mouse.
  269.  
  270.         Arguments:
  271.         - x: X coordinate.
  272.         - y: Y coordinate.
  273.  
  274.         Returns _ItemContext of the component under the mouse.
  275.         '''
  276.         desktop = pyatspi.Registry.getDesktop(0)
  277.         top_window = [
  278.             None,
  279.             -1]
  280.         for app in desktop:
  281.             if not app:
  282.                 continue
  283.             
  284.             script = orca.getScriptForApp(app)
  285.             if not script:
  286.                 continue
  287.             
  288.             for frame in app:
  289.                 if not frame:
  290.                     continue
  291.                 
  292.                 acc = script.getComponentAtDesktopCoords(frame, x, y)
  293.                 if acc:
  294.                     
  295.                     try:
  296.                         z_order = self._getZOrder(frame.name)
  297.                     except ValueError:
  298.                         
  299.                         try:
  300.                             if acc.queryComponent().getLayer() == pyatspi.LAYER_POPUP:
  301.                                 return _ItemContext(x, y, acc, frame, app, script)
  302.  
  303.  
  304.                     if z_order > top_window[-1]:
  305.                         top_window = [
  306.                             _ItemContext(x, y, acc, frame, app, script),
  307.                             z_order]
  308.                     
  309.                 z_order > top_window[-1]
  310.             
  311.         
  312.         return top_window[0]
  313.  
  314.  
  315. if gtk.gdk.display_get_default():
  316.     mouse_reviewer = MouseReviewer()
  317. else:
  318.     raise RuntimeError('Cannot initialize mouse review, no display')
  319.  
  320. def toggle(script = gtk.gdk.display_get_default(), event = None):
  321.     '''
  322.     Toggle the reviewer on or off.
  323.  
  324.     Arguments:
  325.     - script: Given script if this was called as a keybinding callback.
  326.     - event: Given event if this was called as a keybinding callback.
  327.     '''
  328.     mouse_reviewer.toggle()
  329.  
  330.